package  org.fantasy.common.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.web.context.request.WebRequest;

/**
 *  参数获取
 * @author: 王文成
 * @version: 1.0
 * @since 2009-11-26
 */
public final class RequestUtil {
	/**
	 * 无效的数字
	 */
	public static final int INVALID_NUMBER = Integer.MIN_VALUE;

	public static final String EMPTY_STRING = "";

	/**
	 * 特殊的参数
	 */
	public static final Set<String> SPECIALS = new HashSet<String>();

	static {
		SPECIALS.add(Constants.PAGE_SIZE);
		SPECIALS.add(Constants.PAGE_START);
		SPECIALS.add(Constants.PAGE_COUNT);
	}

	/**
	 * 不能创建实例
	 */
	private RequestUtil() {

	}

	/**
	 * 取得Request实现
	 * 
	 * @param request
	 * @return
	 */
	public static Request getWrapRequest(HttpServletRequest request) {
		return new Inner$RequestImpl(request);
	}

	/**
	 * 返回 键值对应 Map
	 * 
	 * @param request
	 * @return
	 */
	public final static Map<String, Object> getRequestMap(HttpServletRequest request) {
		Map<String, Object> map = new HashMap<String, Object>();
		for (Enumeration elements = request.getParameterNames(); elements.hasMoreElements();) {
			String key = (String) elements.nextElement();
			map.put(key, request.getParameter(key));
		}
		return map;
	}
	
	/**
	 * 返回 键值对应 Map
	 * 
	 * @param request
	 * @return
	 */
	public final static ParamMap<String, Object> getParamMap(HttpServletRequest request) {
		Map<String, Object> map = new HashMap<String, Object>();
		for (Enumeration<String> elements = request.getParameterNames(); elements.hasMoreElements();) {
			String key = (String) elements.nextElement();
			map.put(key, request.getParameter(key));
		}
		return new ParamMap<String,Object>(map);
	}

	/**
	 * 返回 键值对应 Map
	 * 
	 * @param request
	 * @return
	 */
	public final static Map<String, Object> getRequestMap(WebRequest request) {
		Map<String, Object> map = new HashMap<String, Object>();
		for (Iterator<String> elements = request.getParameterNames(); elements.hasNext();) {
			String key = (String) elements.next();
			map.put(key, request.getParameter(key));
		}
		return map;
	}

	/**
	 * 返回 键值对应 Map
	 * 
	 * @param request
	 * @return
	 */
	public final static Map<String, Object> getQueryMap(HttpServletRequest request, String prefix) {
		return getQueryMap(request, prefix, new Convert() {
			public Object convert(String key, String value) {
				return value;
			}
		});
	}

	/**
	 * 返回 键值对应 Map
	 * 
	 * @param request
	 * @return
	 */
	public final static Map<String, Object> getQueryMap(HttpServletRequest request) {
		return getQueryMap(request, "ckb");
	}

	/**
	 * 返回 键值对应 Map
	 * 
	 * @param request
	 * @return
	 */
	public final static Map<String, Object> getQueryMap(HttpServletRequest request, String prefix, Convert c) {
		Map<String, Object> qryMap = getRequestMap(request);
		Map<String, Object> paramMap = new HashMap<String, Object>();
		for (Iterator iter = qryMap.entrySet().iterator(); iter.hasNext();) {
			Map.Entry entry = (Map.Entry) iter.next();
			String entryKey = entry.getKey().toString();
			if (SPECIALS.contains(entryKey)) {
				paramMap.put(entryKey, entry.getValue());
			} else if (entryKey.startsWith(prefix) && entryKey.length() > 0) {
				String paramKey = entryKey.replaceAll("^(" + prefix + ")", "");
				String key = StringUtil.firstCharLowerCase(paramKey);
				String value = (String) qryMap.get(key);
				paramMap.put(key, c.convert(key, value));
			}
		}
		return paramMap;
	}

	/**
	 * 返回 键值对应 Map
	 * 
	 * @param request
	 * @return
	 */
	public final static Map<String, Object> getQueryMap(HttpServletRequest request, Convert c) {
		return getQueryMap(request, "ckb", c);
	}

	/**
	 * 获取参数 默认返回空
	 * 
	 * @param request
	 * @param param
	 * @return
	 */
	public final static String getParameter(HttpServletRequest request, String param) {
		return request.getParameter(param);
	}
	
	/**
	 * 取得<html:base/>
	 * @param request
	 * @param param
	 * @return
	 */
	public final static String getBaseURL(HttpServletRequest request) {
		String scheme = request.getScheme();
		String server = request.getServerName();
		int port = request.getServerPort();
		String uri = request.getRequestURI();
		StringBuilder url = new StringBuilder(128);
        url.append(scheme);
        url.append("://");
        url.append(server);
        if ((scheme.equals("http") && (port != 80)) || (scheme.equals("https") && (port != 443))) {
            url.append(':');
            url.append(port);
        }
        url.append(uri);
        return url.toString();
	}

	/**
	 * 获取参数 默认返回空
	 * 
	 * @param request
	 * @param param
	 * @return
	 */
	public final static String getString(HttpServletRequest request, String param) {
		String value = request.getParameter(param);
		return value != null ? value.trim() : EMPTY_STRING;
	}

	/**
	 * 获取参数
	 * 
	 * @param request
	 * @param param
	 * @param defaultValue
	 */
	public final static String getString(HttpServletRequest request, String param, String defaultValue) {
		String value = getString(request, param);
		return value.length() > 0 ? value : defaultValue;
	}

	/**
	 * 获取日期对象
	 * 
	 * @param request
	 * @param param
	 * @param defaultValue
	 */
	public final static java.util.Date getParameterDate(HttpServletRequest request, String param, String parttern) {
		String value = request.getParameter(param);
		return value.length() > 0 ? DateUtil.parse(value, parttern) : null;
	}

	/**
	 * 获取整型数
	 * 
	 * @param request
	 * @param param
	 */
	public final static int getInt(HttpServletRequest request, String param) {
		String value = getString(request, param);
		return value.length() > 0 ? Integer.parseInt(value) : INVALID_NUMBER;
	}

	/**
	 * 获取整型数
	 * 
	 * @param request
	 * @param param
	 * @param defaultValue
	 */
	public final static int getInt(HttpServletRequest request, String param, int defaultValue) {
		String value = getString(request, param);
		return value.length() > 0 ? Integer.parseInt(value) : defaultValue;
	}

	/**
	 * 获取长整型数
	 */
	public final static long getLong(HttpServletRequest request, String param) {
		String value = getString(request, param);
		return value.length() > 0 ? Long.parseLong(value) : INVALID_NUMBER;
	}

	/**
	 * 获取长整型数
	 */
	public final static long getLong(HttpServletRequest request, String param, long defaultValue) {
		String value = getString(request, param);
		return value.length() > 0 ? Long.parseLong(value) : defaultValue;
	}

	/**
	 * 获取参数是有效
	 * 
	 * @param request
	 * @param param
	 * @return
	 */
	public final static boolean getBoolean(HttpServletRequest request, String param) {
		String value = getString(request, param);
		return value.length() > 0;
	}

	/**
	 * 获取参数是有效
	 * 
	 * @param request
	 * @param param
	 * @return
	 */
	public final static boolean isValid(HttpServletRequest request, String param) {
		return getBoolean(request, param);
	}

	/**
	 * 获取 Double
	 * 
	 * @param request
	 * @param param
	 */
	public final static double getDouble(HttpServletRequest request, String param) {
		String value = getString(request, param);
		return value.length() > 0 ? Double.parseDouble(value) : INVALID_NUMBER;
	}

	/**
	 * 获取 Session 中的属性
	 * 
	 * @param session
	 * @param code
	 */
	public final static Object getSessionAttribute(HttpServletRequest request, String key) {
		HttpSession session = request.getSession();
		return session.getAttribute(key);
	}

	/**
	 * 设置 Session 中的属性
	 * 
	 * @param session
	 * @param code
	 */
	public final static void setSessionAttribute(HttpServletRequest request, String key, Object value) {
		HttpSession session = request.getSession();
		session.setAttribute(key, value);
	}

	/**
	 * 设置 Session 中的属性
	 * 
	 * @param session
	 * @param code
	 */
	public final static void removeSessionAttribute(HttpServletRequest request, String key) {
		HttpSession session = request.getSession();
		session.removeAttribute(key);
	}

	/**
	 * 获取 request 中的属性
	 * 
	 * @param request
	 * @param name
	 */
	public final static Object getRequestAttribute(ServletRequest request, String name) {
		return request.getAttribute(name);
	}

	/**
	 * 获取字符串数组
	 * 
	 * @param request
	 * @param param
	 */
	public final static String[] getValues(HttpServletRequest request, String param) {
		String[] values = request.getParameterValues(param);
		return values != null ? values : new String[0];
	}

	/**
	 * 获取字符串数组
	 * 
	 * @param request
	 * @param param
	 */
	public final static String[] getParameterValues(HttpServletRequest request, String param, String[] defaultValues) {
		String[] values = getValues(request, param);
		return values.length > 0 ? values : defaultValues;
	}

	/**
	 * 获取整型数组
	 * 
	 * @param request
	 * @param param
	 */
	public final static int[] getIntValues(HttpServletRequest request, String param) {
		String[] stringValues = getValues(request, param);
		int[] intValues = new int[stringValues.length];
		for (int i = 0; i < stringValues.length; i++) {
			intValues[i] = Integer.parseInt(stringValues[i]);
		}
		return intValues;
	}

	/**
	 * Request接口实现
	 */
	private static class Inner$RequestImpl implements Request {
		private HttpServletRequest request;

		public Inner$RequestImpl(HttpServletRequest request) {
			this.request = request;
		}

		public Map<String, Object> getQryMap(Convert c) {
			return RequestUtil.getQueryMap(this.request, c);
		}

		public String getParameter(String name) {
			return this.request.getParameter(name);
		}

		public String getString(String param, String defaultValue) {
			return RequestUtil.getString(this.request, param, defaultValue);
		}

		public String getString(String param) {
			return RequestUtil.getString(this.request, param);
		}

		public boolean getBoolean(String param) {
			return RequestUtil.getBoolean(this.request, param);
		}

		public boolean isValid(String param) {
			return RequestUtil.getBoolean(this.request, param);
		}

		public Date getDate(String param, String parttern) {
			return RequestUtil.getParameterDate(this.request, param, parttern);
		}

		public double getDouble(String param) {
			return RequestUtil.getDouble(this.request, param);
		}

		public int getInt(String param, int defaultValue) {
			return RequestUtil.getInt(this.request, param);
		}

		public int getInt(String param) {
			return RequestUtil.getInt(this.request, param);
		}

		public int[] getIntValues(String param) {
			return RequestUtil.getIntValues(this.request, param);
		}

		public String[] getParameterValues(String param) {
			return request.getParameterValues(param);
		}

		public long getLong(String param, long defaultValue) {
			return RequestUtil.getLong(this.request, param, defaultValue);
		}

		public long getLong(String param) {
			return RequestUtil.getLong(this.request, param);
		}

		public Map<String, Object> getRequestMap() {
			return RequestUtil.getRequestMap(this.request);
		}

		public String[] getValues(String param) {
			return RequestUtil.getValues(this.request, param);
		}

		public Object getRequestAttribute(String name) {
			return RequestUtil.getRequestAttribute(this.request, name);
		}

		public Object getSessionAttribute(String name) {
			return RequestUtil.getSessionAttribute(this.request, name);
		}

		public Object getAttribute(String key) {
			return this.request.getAttribute(key);
		}

		public Enumeration getAttributeNames() {
			return this.request.getAttributeNames();
		}

		public String getAuthType() {
			return this.request.getAuthType();
		}

		public String getCharacterEncoding() {
			return this.request.getCharacterEncoding();
		}

		public int getContentLength() {
			return this.request.getContentLength();
		}

		public String getContentType() {
			return this.request.getContentType();
		}

		public String getContextPath() {
			return this.request.getContextPath();
		}

		public Cookie[] getCookies() {
			return this.request.getCookies();
		}

		public long getDateHeader(String key) {
			return this.request.getDateHeader(key);
		}

		public String getHeader(String key) {
			return this.request.getHeader(key);
		}

		public Enumeration getHeaderNames() {
			return this.request.getHeaderNames();
		}

		public Enumeration getHeaders(String key) {
			return this.request.getHeaders(key);
		}

		public ServletInputStream getInputStream() throws IOException {
			return this.request.getInputStream();
		}

		public int getIntHeader(String key) {
			return this.request.getIntHeader(key);
		}

		public String getLocalAddr() {
			return this.request.getLocalAddr();
		}

		public Locale getLocale() {
			return this.request.getLocale();
		}

		public Enumeration getLocales() {
			return this.request.getLocales();
		}

		public String getLocalName() {
			return this.request.getLocalName();
		}

		public int getLocalPort() {
			return this.request.getLocalPort();
		}

		public String getMethod() {
			return this.request.getMethod();
		}

		public Map getParameterMap() {
			return this.request.getParameterMap();
		}

		public Enumeration getParameterNames() {
			return this.request.getParameterNames();
		}

		public String getPathInfo() {
			return this.request.getPathInfo();
		}

		public String getPathTranslated() {
			return this.request.getPathTranslated();
		}

		public String getProtocol() {
			return this.request.getProtocol();
		}

		public String getQueryString() {
			return this.request.getQueryString();
		}

		public BufferedReader getReader() throws IOException {
			return this.request.getReader();
		}

		public String getRealPath(String key) {
			ServletContext sc = WebUtil.getServletContext(request);
			return sc.getRealPath(key);
		}

		public String getRemoteAddr() {
			return this.request.getRemoteAddr();
		}

		public String getRemoteHost() {
			return this.request.getRemoteHost();
		}

		public int getRemotePort() {
			return this.request.getRemotePort();
		}

		public String getRemoteUser() {
			return this.request.getRemoteUser();
		}

		public RequestDispatcher getRequestDispatcher(String key) {
			return this.request.getRequestDispatcher(key);
		}

		public String getRequestedSessionId() {
			return this.request.getRequestedSessionId();
		}

		public String getRequestURI() {
			return this.request.getRequestURI();
		}

		public StringBuffer getRequestURL() {
			return this.request.getRequestURL();
		}

		public String getScheme() {
			return this.request.getScheme();
		}

		public String getServerName() {
			return this.request.getServerName();
		}

		public int getServerPort() {
			return this.request.getServerPort();
		}

		public String getServletPath() {
			return this.request.getServletPath();
		}

		public HttpSession getSession() {
			return this.request.getSession();
		}

		public HttpSession getSession(boolean key) {
			return this.request.getSession(key);
		}

		public Principal getUserPrincipal() {
			return this.request.getUserPrincipal();
		}

		public boolean isRequestedSessionIdFromCookie() {
			return this.request.isRequestedSessionIdFromCookie();
		}

		public boolean isRequestedSessionIdFromUrl() {
			return this.request.isRequestedSessionIdFromUrl();
		}

		public boolean isRequestedSessionIdFromURL() {
			return this.request.isRequestedSessionIdFromURL();
		}

		public boolean isRequestedSessionIdValid() {
			return this.request.isRequestedSessionIdValid();
		}

		public boolean isSecure() {
			return this.request.isSecure();
		}

		public boolean isUserInRole(String key) {
			return this.request.isUserInRole(key);
		}

		public void removeAttribute(String key) {
			this.request.removeAttribute(key);
		}

		public void setAttribute(String key, Object value) {
			this.request.setAttribute(key, value);
		}

		public void setCharacterEncoding(String key) throws UnsupportedEncodingException {
			this.request.setCharacterEncoding(key);
		}

		public Map<String, Object> getQryMap() {
			return RequestUtil.getQueryMap(this.request, "ckb");
		}
	}
}